#include "vncviewwidget.h"

#include <QPaintEvent>
#include <QPainter>
#include <QDebug>

#include <cstring>

#include "ElaMessageBar.h"

VncViewWidget::VncViewWidget(QString ip, quint32 port, QWidget *parent) :
    QWidget(parent),
    _ip(ip),
    _port(port)
{
#ifdef TOUCH_MODE
    this->setMouseTracking(false);
#else
    this->setMouseTracking(true);
#endif
    this->setCursor(Qt::BlankCursor);

    _image = QImage(width(), height(), QImage::Format_RGB16);
    _image.fill(Qt::black);

    _vncSendThread = new QThread(this);
    _vncSendWorker = new VNCSendWorker();
    connect(this, &VncViewWidget::sendMouseState, _vncSendWorker, &VNCSendWorker::sendMouseUpdateMsg);
    _vncSendWorker->moveToThread(_vncSendThread);
    _vncRecvThread = new VNCRecvThread(this);
    connect(_vncRecvThread, &VNCRecvThread::updateImageSignal, this, &VncViewWidget::updateImage, Qt::BlockingQueuedConnection);
    connect(_vncRecvThread, &VNCRecvThread::finished, this, &VncViewWidget::stop);

    this->update();
}

VncViewWidget::~VncViewWidget(){
    this->stop();
}

void VncViewWidget::start(){

    if(_startFlag)return;

    _cl = rfbGetClient(8, 3, 2);
    _cl->format.depth = 12;
    _cl->format.bitsPerPixel = 16;
    _cl->format.redShift = 11;
    _cl->format.greenShift = 5;
    _cl->format.blueShift = 0;
    _cl->format.redMax = 0x1f;
    _cl->format.greenMax = 0x3f;
    _cl->format.blueMax = 0x1f;
    _cl->appData.compressLevel = 9;
    _cl->appData.qualityLevel = 1;
    _cl->appData.encodingsString = "hextile";
    _cl->serverHost = strdup(_ip.toStdString().c_str());
    _cl->serverPort = _port;
    _cl->listenPort = 5901;
    _cl->appData.useRemoteCursor = TRUE;
    _cl->readTimeout = 1;
    _cl->connectTimeout = 1;

    if (!rfbInitClient(_cl, 0, nullptr)) {
        ElaMessageBar::error(ElaMessageBarType::BottomRight, "ERROR", "远程初始化失败!", 2000);
        return;
    }

    _vncRecvThread->startRun(_cl);
    _vncSendThread->start();

    _startFlag = true;

    ElaMessageBar::information(ElaMessageBarType::BottomRight, "INFO", "远程连接!", 2000);
}

void VncViewWidget::stop(){

    if(!_startFlag)return;

     _startFlag = false;

    _vncRecvThread->stopRun();
    _vncRecvThread->quit();
    _vncRecvThread->wait();

    _vncSendThread->quit();
    _vncSendThread->wait();

    if(_cl)rfbClientCleanup(_cl);
    _cl = nullptr;

    ElaMessageBar::information(ElaMessageBarType::BottomRight, "INFO", "远程断开!", 2000);
}

void VncViewWidget::updateImage(const QImage& image){
    _image = image;
    this->update();
}

void VncViewWidget::paintEvent(QPaintEvent *event){
    event->accept();
    QPainter painter(this);
    painter.drawImage(this->rect(), _image);
    //ElaMessageBar::error(ElaMessageBarType::BottomRight, QString::number(this->rect().width()), "远程初始化失败!", 2000);
}

void VncViewWidget::mouseMoveEvent(QMouseEvent* event){
    if(_startFlag){
        if(event->buttons() & Qt::LeftButton){
            emit sendMouseState(_cl,
                              event->localPos().x()/width()*_cl->width,
                              event->localPos().y()/height()*_cl->height,
                              1);
        }
        else{
            emit sendMouseState(_cl,
                              event->localPos().x()/width()*_cl->width,
                              event->localPos().y()/height()*_cl->height,
                              0);
        }
    }
}

void VncViewWidget::mousePressEvent(QMouseEvent *event){
    if(_startFlag){
        emit sendMouseState(_cl,
                          event->localPos().x()/width()*_cl->width,
                          event->localPos().y()/height()*_cl->height,
                            1);
    }
}

void VncViewWidget::mouseReleaseEvent(QMouseEvent *event){
    if(_startFlag){
        emit sendMouseState(_cl,
                          event->localPos().x()/width()*_cl->width,
                          event->localPos().y()/height()*_cl->height,
                            0);
    }
}

void VncViewWidget ::closeEvent(QCloseEvent* event){
    emit fullWindowCloseSignal();
    QWidget::closeEvent(event);
}


